home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nfsmount / pdev.c < prev    next >
C/C++ Source or Header  |  1992-05-02  |  41KB  |  1,368 lines

  1. /* 
  2.  * pdev.c --
  3.  *
  4.  *    The routines in this module set up a call-back interface for
  5.  *    a pseudo-device server.  Pdev_Open creates a pseudo-device and
  6.  *    installs service procedures.  These service procedures are called
  7.  *    when client processes use the pseudo-device.  The harness procedure
  8.  *    which invokes the call-backs takes care of the kernel interface.
  9.  *    There are also default service procedures so the user of Pdev_Open
  10.  *    need only provide service procedures for the operations of interest.
  11.  *
  12.  * Copyright 1989 Regents of the University of California
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/pdev.c,v 1.15 90/06/27 11:17:12 shirriff Exp $ SPRITE (Berkeley)";
  24. #endif not lint
  25.  
  26. #include <stdio.h>
  27. #include <sprite.h>
  28. #include <ctype.h>
  29. #include <errno.h>
  30. #include <pdev.h>
  31. #include <list.h>
  32. #include <status.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/file.h>
  36. #include <syslog.h>
  37.  
  38. /*
  39.  * The string below holds an error message if Pdev_Open fails.
  40.  */
  41.  
  42. char pdev_ErrorMsg[150];
  43.  
  44. /*
  45.  * Boolean that can be toggled by applications to get tracing.
  46.  */
  47. int pdev_Trace;
  48.  
  49. /*
  50.  * The Pdev structure is the top-level state for the pseudo-device
  51.  * or pseudo-filelsystem server.  The state for each pseudo-device connection
  52.  * is hung in a list off of this.  This also has a set of default service
  53.  * procedures for the various pseudo-device operations.  Two
  54.  * fields of the Pdev struct are made available to the client of the
  55.  * Pdev package so it can do IOControls on the service stream and
  56.  * set a private data pointer.
  57.  */
  58.  
  59. typedef struct Pdev {
  60.     Pdev_Stream stream;        /* Type PDEV_MAGIC */
  61.     List_Links connectList;    /* List of all service streams for this
  62.                  * pseudo-device (pseudo-filesystem). */
  63.     int requestBufSize;        /* Default request buffer size */
  64.     int readBufSize;        /* Size for optional read buffer */
  65.     Pdev_CallBacks *defaultService;/* Default handlers for pdev operations */
  66. } Pdev;
  67.  
  68. /*
  69.  * The structure below corresponds to a pseudo-device connection between
  70.  * a client and the server.
  71.  */
  72.  
  73. typedef struct ServiceStream {
  74.     Pdev_Stream stream;        /* Type PDEV_STREAM_MAGIC */
  75.     List_Links links;        /* pdev streams are linked into a
  76.                  * list of all streams for the same
  77.                  * pseudo-device (pseudo-file-system). */
  78.     Address parent;        /* Pdev state with which this stream is
  79.                  * associated. */
  80.     int streamID;        /* Sprite identifier for request stream. */
  81.     Address requestBuf;        /* A buffer for requests and data from the
  82.                  * client */
  83.     Address readBuf;        /* A buffer for data to be read over the
  84.                  * pseudo-device by the application. This
  85.                  * is allocated by us and passed to the
  86.                  * read call-back. If read buffering is set
  87.                  * then we allocate this at open-time and
  88.                  * pass it off to the open call-back. */
  89.     int readBufSize;        /* Size of the readBuf. */
  90.     Address ioctlOutBuf;    /* Buffer for results of ioctl */
  91.     int ioctlBufSize;        /* Size of ioctlOutBut */
  92.     Pdev_CallBacks *service;    /* Set of procedures to handle the various
  93.                  * pseudo-device operations. */
  94. } ServiceStream;
  95.  
  96. #define LIST_TO_SRVPTR(listPtr) \
  97.     (ServiceStream *)((int)(listPtr) - sizeof(Pdev_Stream))
  98.  
  99. static int    PdevDefaultOpen();
  100. static int    PdevDefaultRead();
  101. static int    PdevDefaultWrite();
  102. static int    PdevDefaultIoctl();
  103. static int    PdevDefaultClose();
  104. static int    PdevDefaultGetAttr();
  105. static int    PdevDefaultSetAttr();
  106.  
  107. static Pdev_CallBacks pdevDefaultCallBacks = {
  108.      PdevDefaultOpen,
  109.      PdevDefaultRead,
  110.      PdevDefaultWrite,
  111.      PdevDefaultIoctl,
  112.      PdevDefaultClose,
  113.      PdevDefaultGetAttr,
  114.      PdevDefaultSetAttr,
  115. };
  116.  
  117. /*
  118.  * PDEV_MIN_BYTES        Minimum number of data bytes in request buffer.
  119.  * PFS_REQUEST_BUF_SIZE     Size of the request buffer for naming stream.
  120.  */
  121.  
  122. #define PDEV_MIN_BYTES    1024
  123. #define PDEV_REQUEST_BUF_SIZE    (sizeof(Pdev_Request) + PDEV_MIN_BYTES)
  124.  
  125. /*
  126.  * Forward references to procedures in this file:
  127.  */
  128.  
  129. static void    PdevControlRequest();
  130. static void    PdevServiceRequest();
  131. static int    PdevCleanup();
  132. static void    ReplyNoData();
  133. static void    ReplyWithData();
  134. static int    (*SetHandler())();
  135.  
  136. /*
  137.  *----------------------------------------------------------------------
  138.  *
  139.  * Pdev_Open --
  140.  *
  141.  *    Arrange to be the server for a pseudo-device.  This creates the
  142.  *    pseudo-device file, choosing a unique name if needed (see below).
  143.  *    The set of service call-backs are installed and will be called
  144.  *    when regular processes operate on the pseudo-device.  See the
  145.  *    man page for Pdev for details of the call-back interface.
  146.  *
  147.  * Results:
  148.  *    The return value is a token for the pseudo-device, which gets
  149.  *    passed to Pdev_Close.  A NULL return value
  150.  *    means that the pseudo-device could not be opened.  If realNamePtr
  151.  *    is non-NULL, *realNamePtr is filled in with a dynamically-
  152.  *    allocated string giving the actual name of the pseudo-device
  153.  *    file.
  154.  *
  155.  * Side effects:
  156.  *    A pseudo-device is opened in master mode.  If realNamePtr is
  157.  *    NULL then name is the complete name of the pseudo device;  if
  158.  *    realNamePtr is not NULL, then this procedure generates a
  159.  *    pseudo-device name of the form hostDir/nameXX, where "hostDir"
  160.  *    is the name of a standard host-specific directory for holding
  161.  *    terminal pseudo-devices and XX is an integer id appended to
  162.  *    "name" in order to find a device that isn't already in use.
  163.  *    Once this procedure returns, this module manages the pseudo
  164.  *    device to provide a simple call-back interface to service procedures.
  165.  *    I,e, for each operation on the pseudo-device by a another process,
  166.  *    a call-back for that operation is made to one of the supplied
  167.  *    service procedures.
  168.  *
  169.  *----------------------------------------------------------------------
  170.  */
  171.  
  172. Pdev_Token
  173. Pdev_Open(name, realNamePtr, requestBufSize, readBufSize, service, clientData)
  174.     char *name;            /* Name of pseudo-device file to use for
  175.                  * application interface, or key for generating
  176.                  * name (if realNamePtr != NULL).  If no
  177.                  * pseudo-device by that name exists, one
  178.                  * will be created. */
  179.     char **realNamePtr;        /* If not NULL, then use "name" as a key for
  180.                  * a name (see above) and store actual name of
  181.                  * pseudo-device here.  The memory for the
  182.                  * string is dynamically allocated. */
  183.     int requestBufSize;        /* Preferred size for the request buffer.
  184.                  * Can be <= 0 for a default size */
  185.     int readBufSize;        /* Size for optional read buffer.  Zero means
  186.                  * no buffering and we use the read call-back*/
  187.     Pdev_CallBacks *service;    /* A set of service procedures.
  188.                  * This can be NULL (or any element can be
  189.                  * NULL) in order to get a default handler
  190.                  * for all (some) operations.  The callbacks
  191.                  * can be changed with Pdev_SetupHandler */
  192.     ClientData clientData;    /* Client data associated with pseudo-device */
  193. {
  194.     int streamID;
  195.     register Pdev *pdevPtr;
  196.     int pdevOpenFlags;
  197.  
  198.     /*
  199.      * Pick a file name to use for the pseudo-device, if the caller didn't
  200.      * give us one, then open the pseudo-device as the controlling process.
  201.      */
  202.  
  203.     pdevOpenFlags = O_MASTER|O_RDWR|O_CREAT;
  204.     if (realNamePtr != NULL) {
  205.     char hostName[50];
  206.     int i;
  207.     char *actualName;
  208.  
  209.     if (gethostname(hostName, 20) != 0) {
  210.         sprintf(pdev_ErrorMsg, "couldn't get host name (%s)",
  211.             strerror(errno));
  212.         return (Pdev_Token) NULL;
  213.     } else {
  214.         /*
  215.          * Trim off domain name, if any
  216.          */
  217.         char *cp;
  218.  
  219.         cp = index(hostName, '.');
  220.         if (cp != (char *)NULL) {
  221.         *cp = '\0';
  222.         }
  223.     }
  224.     actualName = (char *) malloc((unsigned) (12 + strlen(hostName)
  225.         + strlen(name)));
  226.     for (i = 1; i < 100; i++) {
  227.         sprintf(actualName, "/hosts/%s/%s%d", hostName,
  228.             name, i);
  229.  
  230.         /*
  231.          * Because of umask, the file's mode may not actually get set
  232.          * to 0666.  Once the file is open, change the mode explicitly
  233.          * to force it.
  234.          */
  235.  
  236.         streamID = open(actualName, pdevOpenFlags, 0666);
  237.         if (streamID >= 0) {
  238.         fchmod(streamID, 0666);
  239.         *realNamePtr = actualName;
  240.         goto gotStream;
  241.         }
  242.     }
  243.     free((char *) actualName);
  244.     sprintf(pdev_ErrorMsg, 
  245.         "couldn't open a pseudo-device in \"/hosts/%s\"", hostName);
  246.     return (Pdev_Token) NULL;
  247.     } else {
  248.     streamID = open(name, pdevOpenFlags, 0666);
  249.     if (streamID < 0) {
  250.         sprintf(pdev_ErrorMsg, "couldn't open \"%s\" (%s)",
  251.             name, strerror(errno));
  252.         return (Pdev_Token) NULL;
  253.     } else {
  254.         fchmod(streamID, 0666);
  255.     }
  256.     }
  257.  
  258. gotStream:
  259.     pdevPtr = (Pdev *) malloc(sizeof(Pdev));
  260.     pdevPtr->stream.magic = PDEV_MAGIC;
  261.     pdevPtr->stream.streamID = streamID;
  262.     pdevPtr->stream.clientData = clientData;
  263.     pdevPtr->requestBufSize = requestBufSize;
  264.     pdevPtr->readBufSize = readBufSize;
  265.     List_Init(&pdevPtr->connectList);
  266.     pdevPtr->defaultService = (Pdev_CallBacks *)malloc(sizeof(Pdev_CallBacks));
  267.     if (service == (Pdev_CallBacks *)NULL) {
  268.     bzero((Address) pdevPtr->defaultService, sizeof(Pdev_CallBacks));
  269.     } else {
  270.     bcopy((Address) service, (Address) pdevPtr->defaultService,
  271.             sizeof(Pdev_CallBacks));
  272.     }
  273.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevControlRequest,
  274.         (ClientData) pdevPtr);
  275.  
  276.     return (Pdev_Token) pdevPtr;
  277. }
  278.  
  279. /*
  280.  *----------------------------------------------------------------------
  281.  *
  282.  * Pdev_Close --
  283.  *
  284.  *    Close down a pseudo-device and release all of the
  285.  *    state associated with it.
  286.  *
  287.  * Results:
  288.  *    None.
  289.  *
  290.  * Side effects:
  291.  *    Memory gets recycled, and clients on the other end of the
  292.  *    pseudo-device will probably terminate.  After this call,
  293.  *    the caller should never again use the pseudo-device.
  294.  *
  295.  *----------------------------------------------------------------------
  296.  */
  297.  
  298. void
  299. Pdev_Close(pdevToken)
  300.     Pdev_Token pdevToken;    /* Token identifying the pseudo-device.
  301.                  * This is returned from Pdev_Open. */
  302. {
  303.     register Pdev *pdevPtr = (Pdev *) pdevToken;
  304.     List_Links *listPtr;
  305.     register ServiceStream *srvPtr;
  306.  
  307.     while (!List_IsEmpty(&pdevPtr->connectList)) {
  308.     listPtr = List_First(&pdevPtr->connectList);
  309.     srvPtr = LIST_TO_SRVPTR(listPtr);
  310.     (void)PdevCleanup(srvPtr, FALSE);
  311.     }
  312.     Fs_EventHandlerDestroy(pdevPtr->stream.streamID);
  313.     close(pdevPtr->stream.streamID);
  314.     free((Address)pdevToken);
  315. }
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * Pdev_GetStreamID --
  321.  *
  322.  *    Return the descriptor associated with a master's pdev.  
  323.  *
  324.  * Results:
  325.  *    The streamID is returned.
  326.  *
  327.  * Side effects:
  328.  *    None.
  329.  *
  330.  *----------------------------------------------------------------------
  331.  */
  332.  
  333. int
  334. Pdev_GetStreamID(pdevToken)
  335.     Pdev_Token pdevToken;    /* Token identifying the pseudo-device.
  336.                  * This is returned from Pdev_Open. */
  337. {
  338.     register Pdev *pdevPtr = (Pdev *) pdevToken;
  339.     return(pdevPtr->stream.streamID);
  340. }
  341.  
  342.  
  343. /*
  344.  *----------------------------------------------------------------------
  345.  *
  346.  * PdevCleanup --
  347.  *
  348.  *    Called when a client has closed in order to
  349.  *    clean up any associated state.
  350.  *
  351.  * Results:
  352.  *    Returns the status from the close call-back.
  353.  *
  354.  * Side effects:
  355.  *    Calls the close-call back, then cleans up all state associated
  356.  *    with the pseudo-device.
  357.  *
  358.  *----------------------------------------------------------------------
  359.  */
  360.  
  361. static int
  362. PdevCleanup(srvPtr, sendReply)
  363.     register ServiceStream *srvPtr;    /* Service stream info. */
  364.     Boolean sendReply;            /* TRUE if we should reply to the
  365.                      * close request.  This is done in
  366.                      * normal termination.  FALSE means
  367.                      * no reply needed, used to close
  368.                      * pending connections when the
  369.                      * server is bailing out */
  370. {
  371.     int status;
  372.  
  373.     status = (*srvPtr->service->close)(&srvPtr->stream);
  374. #ifdef lint
  375.     status = PdevDefaultClose(&srvPtr->stream);
  376. #endif /* lint */
  377.  
  378.     if (sendReply) {
  379.     if (status > 200) {
  380.         syslog(LOG_DEBUG,"PdevCleanup: status %d (0x%x)\n",
  381.            status, status);
  382.     }
  383.     ReplyNoData(srvPtr, status, 0);
  384.     }
  385.     List_Remove(&srvPtr->links);
  386.     Fs_EventHandlerDestroy(srvPtr->stream.streamID);
  387.     close(srvPtr->stream.streamID);
  388.     free((char *) srvPtr->requestBuf);
  389.     if (srvPtr->service != (Pdev_CallBacks *)NULL) {
  390.     free((char *) srvPtr->service);
  391.     }
  392.     if (srvPtr->readBuf != NULL) {
  393.     free(srvPtr->readBuf);
  394.     }
  395.     if (srvPtr->ioctlOutBuf != NULL) {
  396.     free(srvPtr->ioctlOutBuf);
  397.     }
  398.     free((char *) srvPtr);
  399.     return status;
  400. }
  401.  
  402. /*
  403.  *----------------------------------------------------------------------
  404.  *
  405.  * PdevControlRequest --
  406.  *
  407.  *    This procedure is invoked by Fs_Dispatcher when the control
  408.  *    stream for a pseudo-device is readable.  This means that
  409.  *    a new stream is being opened on the pdev.
  410.  *
  411.  * Results:
  412.  *    None.
  413.  *
  414.  * Side effects:
  415.  *    Add a new service stream to the pdev.
  416.  *
  417.  *----------------------------------------------------------------------
  418.  */
  419.  
  420. static void
  421. PdevControlRequest(pdevPtr)
  422.     register Pdev *pdevPtr;    /* Pdev whose control stream is ready. */
  423. {
  424.     Pdev_Notify notify;
  425.     int numBytes;
  426.  
  427.     /*
  428.      * Read the control stream for a message containing a new streamID.
  429.      */
  430.  
  431.     numBytes = read(pdevPtr->stream.streamID, (char *) ¬ify, sizeof(notify));
  432.     if (numBytes != sizeof(notify)) {
  433.     panic("%s; status \"%s\", count %d\n",
  434.         "PdevControlRequest couldn't read control stream",
  435.         strerror(errno), numBytes);
  436.     }
  437.     if (notify.magic != PDEV_NOTIFY_MAGIC) {
  438.     panic("%s: %d\n", "PdevControlRequest got bad notify magic number",
  439.         notify.magic);
  440.     }
  441.     (void) PdevSetup(notify.newStreamID, (Address)pdevPtr,
  442.         &pdevPtr->connectList, pdevPtr->requestBufSize,
  443.         pdevPtr->readBufSize, (char *)0, pdevPtr->defaultService, 0);
  444. }
  445.  
  446. /*
  447.  *----------------------------------------------------------------------
  448.  *
  449.  * PdevSetup --
  450.  *
  451.  *    Set up state for a pseudo-device connection. This includes a request
  452.  *    buffer used by the kernel to pass client requests to us and a set
  453.  *    of service call-back procedures.
  454.  *    
  455.  * Results:
  456.  *    A pointer to the user's handle on the service stream.
  457.  *
  458.  * Side effects:
  459.  *    Allocates and initializes state.  Makes IOControls to set
  460.  *    attributes of the pdev connection.
  461.  *
  462.  *----------------------------------------------------------------------
  463.  */
  464.  
  465. Pdev_Stream *
  466. PdevSetup(streamID, backPointer, streamList, reqBufSize, readBufSize, readBuf, service, selectBits)
  467.     int streamID;        /* Service stream */
  468.     Address backPointer;    /* Pointer to global state */
  469.     List_Links *streamList;    /* List of pseudo-device streams */
  470.     int reqBufSize;        /* Size for the request buffer */
  471.     int readBufSize;        /* Size for the read buffer, if any */
  472.     char *readBuf;        /* The read buffer itself, NULL if it should
  473.                  * be allocated here */
  474.     Pdev_CallBacks *service;    /* Set of service call-backs */
  475.     int selectBits;        /* Initial select state of the connection */
  476. {
  477.     register ServiceStream *srvPtr;
  478.     Pdev_SetBufArgs setBuf;
  479.     int false = 0;
  480.  
  481.     srvPtr = (ServiceStream *) malloc(sizeof(ServiceStream));
  482.     List_InitElement(&srvPtr->links);
  483.     List_Insert(&srvPtr->links, LIST_ATFRONT(streamList));
  484.     srvPtr->stream.magic = PDEV_STREAM_MAGIC;
  485.     srvPtr->stream.streamID = streamID;
  486.     srvPtr->stream.clientData = 0;
  487.     srvPtr->parent = backPointer;
  488.     srvPtr->service = (Pdev_CallBacks *)malloc(sizeof(Pdev_CallBacks));
  489.     bcopy((Address) service, (Address) srvPtr->service,
  490.         sizeof(Pdev_CallBacks));
  491.     if (srvPtr->service->open == (int (*)())NULL) {
  492.     srvPtr->service->open = pdevDefaultCallBacks.open;
  493.     }
  494.     if (srvPtr->service->read == (int (*)())NULL) {
  495.     srvPtr->service->read = pdevDefaultCallBacks.read;
  496.     }
  497.     if (srvPtr->service->write == (int (*)())NULL) {
  498.     srvPtr->service->write = pdevDefaultCallBacks.write;
  499.     }
  500.     if (srvPtr->service->ioctl == (int (*)())NULL) {
  501.     srvPtr->service->ioctl = pdevDefaultCallBacks.ioctl;
  502.     }
  503.     if (srvPtr->service->close == (int (*)())NULL) {
  504.     srvPtr->service->close = pdevDefaultCallBacks.close;
  505.     }
  506.     if (srvPtr->service->getAttr == (int (*)())NULL) {
  507.     srvPtr->service->getAttr = pdevDefaultCallBacks.getAttr;
  508.     }
  509.     if (srvPtr->service->setAttr == (int (*)())NULL) {
  510.     srvPtr->service->setAttr = pdevDefaultCallBacks.setAttr;
  511.     }
  512.     if (readBufSize > 0) {
  513.     /*
  514.      * Server wants a read buffer.  We allocate it now and declare
  515.      * it to the kernel with the IOC_PDEV_SET_BUFS call below.
  516.      */
  517.     if (readBuf == NULL) {
  518.         srvPtr->readBuf = malloc(readBufSize);
  519.     } else {
  520.         srvPtr->readBuf = readBuf;
  521.     }
  522.     srvPtr->readBufSize = readBufSize;
  523.     } else {
  524.     /*
  525.      * No read buffering, but we will allocate a buffer for passing
  526.      * to the read service call-back later.
  527.      */
  528.     srvPtr->readBuf = NULL;
  529.     srvPtr->readBufSize = 0;
  530.     }
  531.     srvPtr->ioctlOutBuf = NULL;
  532.     srvPtr->ioctlBufSize = 0;
  533.  
  534.     reqBufSize = max(PDEV_REQUEST_BUF_SIZE, reqBufSize);
  535.     srvPtr->requestBuf = (Address) malloc(reqBufSize);
  536.     setBuf.requestBufAddr = srvPtr->requestBuf;
  537.     setBuf.requestBufSize = reqBufSize;
  538.     setBuf.readBufAddr = srvPtr->readBuf;
  539.     setBuf.readBufSize = srvPtr->readBufSize;
  540.     Fs_IOControl(streamID, IOC_PDEV_WRITE_BEHIND,
  541.             sizeof(int), (Address)&false, 0, (Address) NULL);
  542.     Fs_IOControl(streamID, IOC_PDEV_SET_BUF,
  543.             sizeof(Pdev_SetBufArgs), (Address)&setBuf,
  544.             0, (Address) NULL);
  545.     Fs_IOControl(streamID, IOC_PDEV_READY,
  546.             sizeof(int), (Address)&selectBits, 0, (Address) NULL);
  547.  
  548.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevServiceRequest,
  549.         (ClientData) srvPtr);
  550.  
  551.     return ((Pdev_Stream *)srvPtr);
  552. }
  553.  
  554. /*
  555.  *----------------------------------------------------------------------
  556.  *
  557.  * PdevServiceRequest --
  558.  *
  559.  *    This procedure is invoked by Fs_Dispatch when a request appears
  560.  *    for an service stream.   This procedure reads the request and
  561.  *    dispatches to a routine to handle the request.
  562.  *
  563.  * Results:
  564.  *    None.
  565.  *
  566.  * Side effects:
  567.  *    Makes the call-backs to the service procedures passed to Pdev_Open.
  568.  *    Generates pseudo-device replies to complete the protocol with
  569.  *    the kernel.
  570.  *
  571.  *----------------------------------------------------------------------
  572.  */
  573.  
  574. static void
  575. PdevServiceRequest(srvPtr)
  576.     register ServiceStream *srvPtr;    /* Application stream that has a
  577.                      * request ready for processing. */
  578. {
  579.     Pdev_BufPtrs bufPtrs;
  580.     Pdev_Signal signalInfo;
  581.     Pdev_Request *requestPtr;
  582.     Address dataPtr;        /* pointer to data following header */
  583.     Pdev_Reply reply;
  584.     int numBytes;
  585.     int status;
  586.     int selectBits;
  587.     int savedFirstByte;
  588.  
  589.     /*
  590.      * Read the current pointers for the request buffer.
  591.      */
  592.  
  593.     numBytes = read(srvPtr->stream.streamID, (char *) &bufPtrs,
  594.         sizeof(Pdev_BufPtrs));
  595.     if (numBytes != sizeof(Pdev_BufPtrs)) {
  596.     panic("%s; status \"%s\", count %d\n",
  597.         "PdevServiceRequest had trouble reading request buffer pointers",
  598.         strerror(errno), numBytes);
  599.     }
  600.     if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  601.     panic("%s: %d\n", "PdevServiceRequest got bad pointer magic number",
  602.         bufPtrs.magic);
  603.     }
  604.     savedFirstByte = bufPtrs.requestFirstByte;
  605.     /*
  606.      * While there are still requests in the buffer, service them.
  607.      */
  608.     while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  609.     requestPtr =
  610.         (Pdev_Request *)&srvPtr->requestBuf[bufPtrs.requestFirstByte];
  611.     if (requestPtr->hdr.magic != PDEV_REQUEST_MAGIC) {
  612.         printf("PdevServiceRequest, alignment error: firstByte %d currentByte %d lastByte %d magic %x\n",
  613.           savedFirstByte,
  614.           bufPtrs.requestFirstByte, bufPtrs.requestLastByte,
  615.           requestPtr->hdr.magic);
  616.         /*
  617.          * Ignore bogus request.
  618.          */
  619.         bufPtrs.requestFirstByte = bufPtrs.requestLastByte + 1;
  620.         break;
  621.     }
  622.     dataPtr = (Address)((int)requestPtr + sizeof(Pdev_Request));
  623.     signalInfo.signal = 0;
  624.     signalInfo.code = 0;
  625.  
  626.     switch (requestPtr->hdr.operation) {
  627.         case PDEV_OPEN: {
  628.         /*
  629.          * This is the first operation on a pseudo-device.  The
  630.          * server can set srvPtr->private here, which will be
  631.          * passed into the other handlers.
  632.          */
  633.         Pdev *pdevPtr;
  634.         if (pdev_Trace) {
  635.             fprintf(stderr, "OPEN %d: uid %d use %x",
  636.                 srvPtr->stream.streamID,
  637.                 requestPtr->param.open.uid,
  638.                 requestPtr->param.open.flags);
  639.         }
  640.         pdevPtr = (Pdev *)srvPtr->parent;
  641.         status = (*srvPtr->service->open)
  642.                 (pdevPtr->stream.clientData, &srvPtr->stream,
  643.                 srvPtr->readBuf,
  644.                 requestPtr->param.open.flags,
  645.                 requestPtr->param.open.pid,
  646.                 requestPtr->param.open.hostID,
  647.                 requestPtr->param.open.uid,
  648.                 &selectBits);
  649. #ifdef lint
  650.         status = PdevDefaultOpen(pdevPtr->stream.clientData, &srvPtr->stream,
  651.                 srvPtr->readBuf,
  652.                 requestPtr->param.open.flags,
  653.                 requestPtr->param.open.pid,
  654.                 requestPtr->param.open.hostID,
  655.                 requestPtr->param.open.uid,
  656.                 &selectBits);
  657. #endif /* lint */
  658.         if (status > 200) {
  659.             syslog(LOG_DEBUG,"PdevServReq (open): status %d (0x%x)\n",
  660.                status, status);
  661.         }
  662.         ReplyNoData(srvPtr, status, selectBits);
  663.         break;
  664.         }
  665.         case PDEV_CLOSE:
  666.         if (pdev_Trace) {
  667.             fprintf(stderr, "CLOSE %d", srvPtr->stream.streamID);
  668.         }
  669.         status = PdevCleanup(srvPtr, TRUE);
  670.         break;
  671.         case PDEV_READ: {
  672.         /*
  673.          * For reading we pass in a pre-allocated buffer, but also
  674.          * allow the read procedure to use a different buffer.  If it
  675.          * does change the buffer it also indicates if we should
  676.          * free the new buffer after we reply.  We hold onto our
  677.          * own srvPtr->readBuf until the connection is closed.
  678.          */
  679.         Boolean freeIt = FALSE;
  680.  
  681.         if (pdev_Trace) {
  682.             fprintf(stderr, "READ %d bytes at offset %d\n",
  683.             requestPtr->hdr.replySize,
  684.             requestPtr->param.read.offset);
  685.         }
  686.  
  687.         reply.replySize = requestPtr->hdr.replySize;
  688.         if (reply.replySize > srvPtr->readBufSize) {
  689.             /*
  690.              * Increase the read buffer size.
  691.              */
  692.             if (srvPtr->readBuf != NULL) {
  693.             free(srvPtr->readBuf);
  694.             }
  695.             srvPtr->readBuf = malloc(reply.replySize);
  696.             srvPtr->readBufSize = reply.replySize;
  697.         }
  698.         requestPtr->param.read.buffer = srvPtr->readBuf;
  699.         status = (*srvPtr->service->read)(&srvPtr->stream,
  700.                 &requestPtr->param.read, &freeIt,
  701.                 &reply.selectBits,
  702.                 &signalInfo);
  703. #ifdef lint
  704.         status = PdevDefaultRead(&srvPtr->stream,
  705.                 &requestPtr->param.read, &freeIt,
  706.                 &reply.selectBits,
  707.                 &signalInfo);
  708. #endif /* lint */
  709.  
  710.         reply.replySize = requestPtr->param.read.length;
  711.         reply.replyBuf = requestPtr->param.read.buffer;
  712.         ReplyWithData(srvPtr, status, &reply, &signalInfo);
  713.         if (freeIt &&
  714.             (requestPtr->param.read.buffer != srvPtr->readBuf)) {
  715.             free(requestPtr->param.read.buffer);
  716.         }
  717.         break;
  718.         }
  719.         case PDEV_WRITE_ASYNC:
  720.         case PDEV_WRITE: {
  721.         if (pdev_Trace) {
  722.             fprintf(stderr, "WRITE %d bytes at offset %d",
  723.             requestPtr->hdr.requestSize,
  724.             requestPtr->param.read.offset);
  725.         }
  726.         requestPtr->param.write.buffer = dataPtr;
  727.         status = (*srvPtr->service->write)(&srvPtr->stream,
  728.                 (requestPtr->hdr.operation == PDEV_WRITE_ASYNC),
  729.                 &requestPtr->param.write,
  730.                 &reply.selectBits,
  731.                 &signalInfo);
  732. #ifdef lint
  733.         status = PdevDefaultWrite(&srvPtr->stream,
  734.                 (requestPtr->hdr.operation == PDEV_WRITE_ASYNC),
  735.                 &requestPtr->param.write,
  736.                 &reply.selectBits,
  737.                 &signalInfo);
  738. #endif /* lint */
  739.         if (requestPtr->hdr.operation == PDEV_WRITE) {
  740.             reply.replySize = sizeof(int);
  741.             reply.replyBuf = (Address)&requestPtr->param.write.length;
  742.             ReplyWithData(srvPtr, status, &reply, &signalInfo);
  743.         }
  744.         break;
  745.         }
  746.         case PDEV_IOCTL: {
  747.         if (pdev_Trace) {
  748.             fprintf(stderr, "IOCTL %d", requestPtr->param.ioctl.command);
  749.         }
  750.         /*
  751.          * The kernel sets up the sizes of the two buffers,
  752.          * but we have our own notion of where they are.
  753.          * We grow the out buffer if needed, for example,
  754.          * and the inBuffer is sitting in the request buffer at dataPtr.
  755.          */
  756.         reply.replySize = requestPtr->hdr.replySize;
  757.         if (reply.replySize > srvPtr->ioctlBufSize) {
  758.             if (srvPtr->ioctlOutBuf != NULL) {
  759.             free(srvPtr->ioctlOutBuf);
  760.             }
  761.             srvPtr->ioctlOutBuf = malloc(reply.replySize);
  762.             srvPtr->ioctlBufSize = reply.replySize;
  763.         }
  764.         requestPtr->param.ioctl.inBuffer = dataPtr;
  765.         requestPtr->param.ioctl.outBuffer = srvPtr->ioctlOutBuf;
  766.         status = (*srvPtr->service->ioctl)(&srvPtr->stream,
  767.                  &requestPtr->param.ioctl,
  768.                  &reply.selectBits,
  769.                  &signalInfo);
  770. #ifdef lint
  771.         status = PdevDefaultIoctl(&srvPtr->stream,
  772.                  &requestPtr->param.ioctl,
  773.                  &reply.selectBits,
  774.                  &signalInfo);
  775. #endif /* lint */
  776.         reply.replyBuf = srvPtr->ioctlOutBuf;
  777.         reply.replySize = requestPtr->param.ioctl.outBufSize;
  778.         ReplyWithData(srvPtr, status, &reply, &signalInfo);
  779.         break;
  780.         }
  781.         case PDEV_GET_ATTR: {
  782.         Fs_Attributes attr;
  783.  
  784.         if (pdev_Trace) {
  785.             fprintf(stderr, "GET ATTR");
  786.         }
  787.         status = (*srvPtr->service->getAttr)(&srvPtr->stream,
  788.                 &attr, &reply.selectBits);
  789. #ifdef lint
  790.         status = PdevDefaultGetAttr(&srvPtr->stream,
  791.                 &attr, &reply.selectBits);
  792. #endif /* lint */
  793.         if (status == SUCCESS) {
  794.             reply.replyBuf = (Address)&attr;
  795.             reply.replySize = sizeof(Fs_Attributes);
  796.             ReplyWithData(srvPtr, status, &reply, (Pdev_Signal *)NIL);
  797.         } else {
  798.             if (status > 200) {
  799.             syslog(LOG_DEBUG,"PdevServReq (Ioctl): status %d (0x%x)\n",
  800.                    status, status);
  801.             }
  802.             ReplyNoData(srvPtr, status, reply.selectBits);
  803.         }
  804.         break;
  805.         }
  806.         case PDEV_SET_ATTR: {
  807.         if (pdev_Trace) {
  808.             fprintf(stderr, "SET ATTR %x", requestPtr->param.setAttr.flags);
  809.         }
  810.         status = (*srvPtr->service->setAttr)(&srvPtr->stream,
  811.                 requestPtr->param.setAttr.flags,
  812.                 requestPtr->param.setAttr.uid,
  813.                 requestPtr->param.setAttr.gid,
  814.                 (Fs_Attributes *)dataPtr, &reply.selectBits);
  815. #ifdef lint
  816.         status = PdevDefaultSetAttr(&srvPtr->stream,
  817.                 requestPtr->param.setAttr.flags,
  818.                 requestPtr->param.setAttr.uid,
  819.                 requestPtr->param.setAttr.gid,
  820.                 (Fs_Attributes *)dataPtr, &reply.selectBits);
  821. #endif /* lint */
  822.         if (status > 200) {
  823.             syslog(LOG_DEBUG,"PdevServReq (get_attr): status %d (0x%x)\n",
  824.                status, status);
  825.         }
  826.         ReplyNoData(srvPtr, status, reply.selectBits);
  827.         break;
  828.         }
  829.         default:
  830.         panic("PdevServiceRequest: bad request on request stream: %d\n",
  831.             requestPtr->hdr.operation);
  832.     }
  833.     if (pdev_Trace) {
  834.         fprintf(stderr, " Returns %x\n", status);
  835.     }
  836.     /*
  837.      * Move to the next request message.
  838.      */
  839.     bufPtrs.requestFirstByte += requestPtr->hdr.messageSize;
  840.     }
  841.     /*
  842.      * Tell the kernel we processed the requests.
  843.      */
  844.     Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_SET_PTRS,
  845.             sizeof(Pdev_BufPtrs), (Address)&bufPtrs,
  846.             0, (Address) NULL);
  847. }
  848.  
  849. /*
  850.  *----------------------------------------------------------------------
  851.  *
  852.  * ReplyNoData --
  853.  *
  854.  *    Send a reply back with no data;  just a return status.  This
  855.  *    procedure is most often used for error returns.
  856.  *
  857.  * Results:
  858.  *    None.
  859.  *
  860.  * Side effects:
  861.  *    The application will receive status as the return from the
  862.  *    system call it invoked.
  863.  *
  864.  *----------------------------------------------------------------------
  865.  */
  866.  
  867. static void
  868. ReplyNoData(srvPtr, status, selectBits)
  869.     ServiceStream *srvPtr;    /* Application stream info. */
  870.     int status;    /* Error code to send to application. */
  871.     int selectBits;        /* Current select state for the stream */
  872. {
  873.     Pdev_Reply reply;
  874.  
  875.     reply.magic = PDEV_REPLY_MAGIC;
  876.     reply.selectBits = selectBits;
  877.     if (status == EWOULDBLOCK) {
  878.     status = FS_WOULD_BLOCK;
  879.     } else {
  880.     status = Compat_MapToSprite(status);
  881.     }
  882.     reply.status = status;
  883.     reply.replySize = 0;
  884.     reply.replyBuf = NULL;
  885.     reply.signal = 0;
  886.     reply.code = 0;
  887.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_REPLY,
  888.         sizeof(Pdev_Reply), (Address) &reply, 0, (Address) NULL);
  889.     if (status != SUCCESS) {
  890.     panic("%s; status \"%s\"\n", "Reply couldn't send pdev reply",
  891.         Stat_GetMsg(status));
  892.     }
  893. }
  894.  
  895. /*
  896.  *----------------------------------------------------------------------
  897.  *
  898.  * ReplyWithData --
  899.  *
  900.  *    Send a reply back along with some data.
  901.  *
  902.  * Results:
  903.  *    None.
  904.  *
  905.  * Side effects:
  906.  *    The application will receive status as the return from the
  907.  *    system call it invoked.
  908.  *
  909.  *----------------------------------------------------------------------
  910.  */
  911.  
  912. static void
  913. ReplyWithData(srvPtr, status, replyPtr, sigPtr)
  914.     ServiceStream *srvPtr;    /* Application stream info. */
  915.     int status;            /* Error code to send to application. */
  916.     Pdev_Reply *replyPtr;    /* Partially completed reply.  The replySize,
  917.                  * data area, and selectBits should be set. */
  918.     Pdev_Signal *sigPtr;    /* Signal to return, if any */
  919. {
  920.     if (status == EWOULDBLOCK) {
  921.     status = FS_WOULD_BLOCK;
  922.     } else {
  923.     status = Compat_MapToSprite(status);
  924.     }
  925.     if (sigPtr != (Pdev_Signal *)NIL) {
  926.     replyPtr->signal = sigPtr->signal;
  927.     replyPtr->code = sigPtr->code;
  928.     } else {
  929.     replyPtr->signal = 0;
  930.     replyPtr->code = 0;
  931.     }
  932.     if (replyPtr->replySize <= PDEV_SMALL_DATA_LIMIT) {
  933.     Pdev_ReplyData replyData;
  934.  
  935.     replyData.magic = PDEV_REPLY_DATA_MAGIC;
  936.     replyData.status = status;
  937.     replyData.selectBits = replyPtr->selectBits;
  938.     replyData.replySize = replyPtr->replySize;
  939.     replyData.signal = replyPtr->signal;
  940.     replyData.code = replyPtr->code;
  941.     bcopy(replyPtr->replyBuf, replyData.data, replyPtr->replySize);
  942.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_SMALL_REPLY,
  943.         sizeof(Pdev_ReplyData), (Address)&replyData, 0, (Address) NULL);
  944.     } else {
  945.     replyPtr->magic = PDEV_REPLY_MAGIC;
  946.     replyPtr->status = status;
  947.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_REPLY,
  948.             sizeof(Pdev_Reply), (Address) replyPtr, 0, (Address) NULL);
  949.     }
  950.     if (status != SUCCESS) {
  951.     panic("%s; status \"%s\"\n", "ReplyWithData couldn't send pdev reply",
  952.         Stat_GetMsg(status));
  953.     }
  954. }
  955.  
  956. /*
  957.  *----------------------------------------------------------------------
  958.  *
  959.  * Pdev_EnumStreams --
  960.  *
  961.  *    Apply a function to all service streams associated with a pdev.
  962.  *
  963.  * Results:
  964.  *    0 means all the applications of the function returned 0 as well.
  965.  *    If the function returns non-zero when applied to a stream then
  966.  *    the enumeration is stopped and that value is returned.
  967.  *
  968.  * Side effects:
  969.  *    None here.
  970.  *
  971.  *----------------------------------------------------------------------
  972.  */
  973.  
  974. int
  975. Pdev_EnumStreams(pdevToken, func, clientData)
  976.     Pdev_Token pdevToken;
  977.     int (*func)();
  978.     ClientData clientData;
  979. {
  980.     register Pdev *pdevPtr = (Pdev *)pdevToken;
  981.     register List_Links *listPtr;
  982.     register ServiceStream *srvPtr;
  983.     register int status;
  984.  
  985.     if (pdevPtr->stream.magic != (unsigned int)PDEV_MAGIC) {
  986.     fprintf(stderr, "Pdev_EnumStreams passed bad pdevToken\n");
  987.     return -1;
  988.     }
  989.     LIST_FORALL(&pdevPtr->connectList, listPtr) {
  990.     srvPtr = LIST_TO_SRVPTR(listPtr);
  991.     status = (*func)((Pdev_Stream *)srvPtr, clientData);
  992.     if (status != 0) {
  993.         return(status);
  994.     }
  995.     }
  996.     return(0);
  997. }
  998.  
  999.  
  1000. /*
  1001.  *----------------------------------------------------------------------
  1002.  *
  1003.  * Pfs_SetDefaultHandler --
  1004.  *
  1005.  *    Set a default handler for a particular PDEV request.  If the handler is
  1006.  *    NULL then a default procedure replaces the existing handler.
  1007.  *    The default handlers are used when new connections are established
  1008.  *    to the pseudo-device.
  1009.  * 
  1010.  * Results:
  1011.  *    The old handler.
  1012.  *
  1013.  * Side effects:
  1014.  *    Updates the call-back list.
  1015.  *
  1016.  *----------------------------------------------------------------------
  1017.  */
  1018. int (*
  1019. Pdev_SetDefaultHandler(token, operation, handler))()
  1020.     Pdev_Token token;        /* Returned from Pdev_Open */
  1021.     int operation;        /* Which operation to set the handler for */
  1022.     int (*handler)();        /* The callback procedure */
  1023. {
  1024.     register Pdev        *pdevPtr = (Pdev *)token;
  1025.     register int        (*oldHandler)();
  1026.  
  1027.     if (pdevPtr->stream.magic != (unsigned int)PDEV_MAGIC) {
  1028.     fprintf(stderr, "Bad token passed to Pdev_SetHandler\n");
  1029.     return (int (*)())NULL;
  1030.     }
  1031.  
  1032.     oldHandler = SetHandler(pdevPtr->defaultService, operation, handler);
  1033.     return oldHandler;
  1034. }
  1035.  
  1036. /*
  1037.  *----------------------------------------------------------------------
  1038.  *
  1039.  * Pfs_SetStreamHandler --
  1040.  *
  1041.  *    Set a handler for a particular stream and PDEV request.  If the handler
  1042.  *    is NULL then a default procedure replaces the existing handler.
  1043.  *    This call only affects the handler for the given stream to the
  1044.  *    pseudo-device.
  1045.  * 
  1046.  * Results:
  1047.  *    The old handler.
  1048.  *
  1049.  * Side effects:
  1050.  *    Updates the call-back list.
  1051.  *
  1052.  *----------------------------------------------------------------------
  1053.  */
  1054. int (*
  1055. Pdev_SetStreamHandler(streamPtr, operation, handler))()
  1056.     Pdev_Stream *streamPtr;/* Handler for stream to pseudo-device */
  1057.     int operation;        /* Which operation to set the handler for */
  1058.     int (*handler)();        /* The callback procedure */
  1059. {
  1060.     register ServiceStream    *srvPtr = (ServiceStream *)streamPtr;
  1061.     register int        (*oldHandler)();
  1062.  
  1063.     if (srvPtr->stream.magic != (unsigned int)PDEV_STREAM_MAGIC) {
  1064.     fprintf(stderr, "Bad token passed to Pdev_SetHandler\n");
  1065.     return (int (*)())NULL;
  1066.     }
  1067.  
  1068.     oldHandler = SetHandler(srvPtr->service, operation, handler);
  1069.     return oldHandler;
  1070. }
  1071.  
  1072. /*
  1073.  *----------------------------------------------------------------------
  1074.  *
  1075.  * SetHandler --
  1076.  *
  1077.  *    Set the handler for a pseudo-device operation and return the
  1078.  *    old handler.
  1079.  *
  1080.  * Results:
  1081.  *    The old handler.
  1082.  *
  1083.  * Side effects:
  1084.  *    Change the handler.
  1085.  *
  1086.  *----------------------------------------------------------------------
  1087.  */
  1088.  
  1089. static int (*
  1090. SetHandler(service, operation, handler))()
  1091.     Pdev_CallBacks *service;
  1092.     int operation;
  1093.     int (*handler)();
  1094. {
  1095.     int (*oldHandler)();
  1096.  
  1097.     switch (operation) {
  1098.     case PDEV_OPEN:
  1099.         oldHandler = service->open;
  1100.         if (handler == (int (*)())NULL) {
  1101.         service->open = pdevDefaultCallBacks.open;
  1102.         } else {
  1103.         service->open = handler;
  1104.         }
  1105.         break;
  1106.     case PDEV_CLOSE:
  1107.         oldHandler = service->close;
  1108.         if (handler == (int (*)())NULL) {
  1109.         service->close = pdevDefaultCallBacks.close;
  1110.         } else {
  1111.         service->close = handler;
  1112.         }
  1113.         break;
  1114.     case PDEV_READ:
  1115.         oldHandler = service->read;
  1116.         if (handler == (int (*)())NULL) {
  1117.         service->read = pdevDefaultCallBacks.read;
  1118.         } else {
  1119.         service->read = handler;
  1120.         }
  1121.         break;
  1122.     case PDEV_WRITE:
  1123.         oldHandler = service->write;
  1124.         if (handler == (int (*)())NULL) {
  1125.         service->write = pdevDefaultCallBacks.write;
  1126.         } else {
  1127.         service->write = handler;
  1128.         }
  1129.         break;
  1130.     case PDEV_IOCTL:
  1131.         oldHandler = service->ioctl;
  1132.         if (handler == (int (*)())NULL) {
  1133.         service->ioctl = pdevDefaultCallBacks.ioctl;
  1134.         } else {
  1135.         service->ioctl = handler;
  1136.         }
  1137.         break;
  1138.     case PDEV_GET_ATTR:
  1139.         oldHandler = service->getAttr;
  1140.         if (handler == (int (*)())NULL) {
  1141.         service->getAttr = pdevDefaultCallBacks.getAttr;
  1142.         } else {
  1143.         service->getAttr = handler;
  1144.         }
  1145.         break;
  1146.     case PDEV_SET_ATTR:
  1147.         oldHandler = service->setAttr;
  1148.         if (handler == (int (*)())NULL) {
  1149.         service->setAttr = pdevDefaultCallBacks.setAttr;
  1150.         } else {
  1151.         service->setAttr = handler;
  1152.         }
  1153.         break;
  1154.     default:
  1155.         fprintf(stderr, "Bad operation passed to Pdev_SetHandler");
  1156.         oldHandler = (int (*)())NULL;
  1157.         break;
  1158.     }
  1159.     return oldHandler;
  1160. }
  1161.  
  1162. /*
  1163.  *----------------------------------------------------------------------
  1164.  *
  1165.  * PdevDefaultOpen --
  1166.  *
  1167.  *    Default procedure is called when an PDEV_OPEN request is
  1168.  *    received over an service stream.
  1169.  *
  1170.  * Results:
  1171.  *    Returns SUCCESS and the select state of the pseudo-device.
  1172.  *
  1173.  * Side effects:
  1174.  *    None.
  1175.  *
  1176.  *----------------------------------------------------------------------
  1177.  */
  1178. /*ARGSUSED*/
  1179. static int
  1180. PdevDefaultOpen(clientData, streamPtr, readBuf, flags, procID, hostID,
  1181.     uid, selectBitsPtr)
  1182.     ClientData clientData;    /* Client data associated with pseudo-device */
  1183.     Pdev_Stream *streamPtr;    /* Identifies open stream */
  1184.     char *readBuf;        /* Optional read buffer */
  1185.     int flags;            /* Flags passed to open system call */
  1186.     int procID;            /* Process ID doing the open */
  1187.     int hostID;            /* Host on which process is executing */
  1188.     int uid;            /* User id of process */
  1189.     int *selectBitsPtr;        /* Return - select state of pseudo-device */
  1190. {
  1191.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1192.     return(SUCCESS);
  1193. }
  1194.  
  1195. /*
  1196.  *----------------------------------------------------------------------
  1197.  *
  1198.  * PdevDefaultClose --
  1199.  *
  1200.  *    Default procedure is called when an PDEV_CLOSE request is
  1201.  *    received over an service stream.
  1202.  *
  1203.  * Results:
  1204.  *    Returns SUCCESS and the select state of the pseudo-device.
  1205.  *
  1206.  * Side effects:
  1207.  *    None.
  1208.  *
  1209.  *----------------------------------------------------------------------
  1210.  */
  1211. /*ARGSUSED*/
  1212. static int
  1213. PdevDefaultClose(streamPtr)
  1214.     Pdev_Stream *streamPtr;
  1215. {
  1216.     return(SUCCESS);
  1217. }
  1218.  
  1219. /*
  1220.  *----------------------------------------------------------------------
  1221.  *
  1222.  * PdevDefaultRead --
  1223.  *
  1224.  *    The default read procedure.  This simulates EOF by returning
  1225.  *    SUCCESS but no characters.
  1226.  *
  1227.  * Results:
  1228.  *    None.
  1229.  *
  1230.  * Side effects:
  1231.  *    None.
  1232.  *
  1233.  *----------------------------------------------------------------------
  1234.  */
  1235. /*ARGSUSED*/
  1236. static int
  1237. PdevDefaultRead(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
  1238.     Pdev_Stream *streamPtr;    /* Service stream. */
  1239.     Pdev_RWParam *readPtr;    /* Read parameter block. */
  1240.     Boolean *freeItPtr;        /* Return indicates if *bufferPtr is malloc'd */
  1241.     int *selectBitsPtr;        /* Return - the select state of the pdev */
  1242.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1243. {
  1244.     *freeItPtr = FALSE;
  1245.     readPtr->length = 0;
  1246.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1247.     return(SUCCESS);
  1248. }
  1249.  
  1250. /*
  1251.  *----------------------------------------------------------------------
  1252.  *
  1253.  * PdevDefaultWrite --
  1254.  *
  1255.  *    The default write procedure.  This accepts and discards all data.
  1256.  *
  1257.  * Results:
  1258.  *    None.
  1259.  *
  1260.  * Side effects:
  1261.  *    None.
  1262.  *
  1263.  *----------------------------------------------------------------------
  1264.  */
  1265.  
  1266. /*ARGSUSED*/
  1267. static int
  1268. PdevDefaultWrite(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
  1269.     Pdev_Stream *streamPtr;    /* Private data */
  1270.     int async;            /* TRUE if asynchronous and no reply needed */
  1271.     Pdev_RWParam *writePtr;    /* Write parameter block. */
  1272.     int *selectBitsPtr;        /* Result - select state of the pseudo-device */
  1273.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1274. {
  1275.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1276.     return(SUCCESS);
  1277. }
  1278.  
  1279. /*
  1280.  *----------------------------------------------------------------------
  1281.  *
  1282.  * PdevDefaultIoctl --
  1283.  *
  1284.  *    The default IOControl handling procedure called when an
  1285.  *    PDEV_IOCONTROL request is received over a request stream.
  1286.  *
  1287.  * Results:
  1288.  *    None.
  1289.  *
  1290.  * Side effects
  1291.  *    None.
  1292.  *
  1293.  *----------------------------------------------------------------------
  1294.  */
  1295. /*ARGSUSED*/
  1296. static int
  1297. PdevDefaultIoctl(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
  1298.     Pdev_Stream *streamPtr;    /* Stream to service. */
  1299.     Pdev_IOCParam *ioctlPtr;    /* ioctl parameter block. */
  1300.     int *selectBitsPtr;        /* Return - select state of pdev. */
  1301.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1302. {
  1303.     ioctlPtr->outBufSize = 0;
  1304.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1305.     return(SUCCESS);
  1306. }
  1307.  
  1308. /*
  1309.  *----------------------------------------------------------------------
  1310.  *
  1311.  * PdevDefaultGetAttr --
  1312.  *
  1313.  *    The default GetAttributes handling procedure called when an
  1314.  *    PDEV_GET_ATTR request is received over a request stream.
  1315.  *
  1316.  * Results:
  1317.  *    None.
  1318.  *
  1319.  * Side effects
  1320.  *    None.
  1321.  *
  1322.  *----------------------------------------------------------------------
  1323.  */
  1324. /*ARGSUSED*/
  1325. static int
  1326. PdevDefaultGetAttr(streamPtr, attrPtr, selectBitsPtr)
  1327.     Pdev_Stream *streamPtr;
  1328.     Fs_Attributes *attrPtr;
  1329.     int *selectBitsPtr;
  1330. {
  1331.     bzero((Address)attrPtr, sizeof(Fs_Attributes));
  1332.     attrPtr->fileNumber = (int)streamPtr->clientData;
  1333.     attrPtr->permissions = 0644;
  1334.     attrPtr->type = FS_FILE;
  1335.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1336.     return(SUCCESS);
  1337. }
  1338.  
  1339. /*
  1340.  *----------------------------------------------------------------------
  1341.  *
  1342.  * PdevDefaultSetAttr --
  1343.  *
  1344.  *    The default GetAttributes handling procedure called when an
  1345.  *    PDEV_SET_ATTR request is received over a request stream.
  1346.  *
  1347.  * Results:
  1348.  *    None.
  1349.  *
  1350.  * Side effects
  1351.  *    None.
  1352.  *
  1353.  *----------------------------------------------------------------------
  1354.  */
  1355. /*ARGSUSED*/
  1356. static int
  1357. PdevDefaultSetAttr(streamPtr, flags, uid, gid, attrPtr, selectBitsPtr)
  1358.     Pdev_Stream *streamPtr;
  1359.     int flags;
  1360.     int uid;
  1361.     int gid;
  1362.     Fs_Attributes *attrPtr;
  1363.     int *selectBitsPtr;
  1364. {
  1365.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1366.     return(SUCCESS);
  1367. }
  1368.